package ch.fhnw.apsi.filter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

import ch.fhnw.apsi.Page;

/**
 * Servlet Filter implementation class FilterDOS. Dies limitiert die gleichzeitigen Anfragen per IP-Adresse.
 */
@WebFilter(filterName = "filter-dos", description = "Filter dos by IP adress.", urlPatterns = { "/*" })
public final class FilterDOS implements Filter {
  private static final int LIMIT = 3;
  private final Map<String, AtomicInteger> requests = new HashMap<>();

  public FilterDOS() {
  }

  @Override
  public void destroy() {
    // ...
  }

  @Override
  public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
      throws IOException, ServletException {
    final String ip = request.getRemoteAddr();
    final AtomicInteger counter;
    synchronized (this.requests) {
      if (!this.requests.containsKey(ip))
        this.requests.put(ip, counter = new AtomicInteger(0));
      else
        counter = this.requests.get(ip);
    }
    if (counter.incrementAndGet() > LIMIT) {
      try {
        Thread.sleep(500);
      } catch (final InterruptedException e) {
        return;
      }
      request.setAttribute("page", Page.ERROR);
      request.setAttribute("error", "Der Server ist überlastet.");
      request.setAttribute("status", 503);
    }
    try {
      chain.doFilter(request, response);
    } finally {
      counter.decrementAndGet();
    }
  }

  @Override
  public void init(final FilterConfig fConfig) throws ServletException {
    // ...
  }

}
